<template>
  <div class="itembox">
    <div class="item" style="position: absolute; z-index: -1;" :style="itemStyle">
      <div v-if="data.hasHead" class="item__head" :style="itemHeadStyle"></div>
      {{ data.text }}
      <div v-if="data.hasTail" class="item__tail" :style="itemTailStyle"></div>
    </div>
    <div class="item" ref="item" :style="itemStyle">
      <div v-if="data.hasHead" class="item__head" :style="itemHeadStyle"></div>
      {{ data.text }}
      <div v-if="data.hasTail" class="item__tail" :style="itemTailStyle"></div>
    </div>
  </div>
</template>

<script>
import { TweenMax } from 'gsap'
import Draggable from 'gsap/Draggable'

export default {
  props: {
    option: {},
    data: {
      default: () => {
        return {
          text: '节点', // 文本内容
          color: 'black', // 文本颜色
          bgColor: '#409eff', // 背景颜色
          hasHead: true, // 是否有头节点
          hasTail: true // 是否有尾节点
        }
      }
    }
  },
  data () {
    return {}
  },
  methods: {
    isEnterBox (event, rect) {
      return event.clientX > rect.left && event.clientX < rect.right && event.clientY > rect.top && event.clientY < rect.bottom
    },
    init (stage) {
      this.stage = stage
      const dom = this.stage.$el
      let offsetX
      let offsetY
      this.node = Draggable.create(this.$refs.item, {
        type: 'x,y',
        edgeResistance: 0.65,
        cursor: 'default',
        activeCursor: 'default',
        inertia: true,
        onPress: event => {
          offsetX = event.offsetX
          offsetY = event.offsetY
          // console.log(event.offsetX, event.offsetY)
        },
        onDragEnd: event => {
          const rect = dom.getBoundingClientRect()
          if (!this.isEnterBox(event, rect)) {
            TweenMax.to(this.$refs.item, 0.5, { x: 0, y: 0 })
          } else {
            TweenMax.to(this.$refs.item, 0, { x: 0, y: 0 })
            const point = this.stage.getPoint(event)
            // const x = event.clientX - offsetX - rect.left - 1
            // const y = event.clientY - offsetY - rect.top - 1
            const x = point.x - offsetX - 1 - this.opt.node.borderWidth / 2 // 1是拖动后的微小偏移
            const y = point.y - offsetY - 1 - this.opt.node.borderWidth / 2
            // console.log(point.x, offsetX)
            stage.addNode({
              x,
              y,
              text: this.data.text,
              color: this.data.color,
              bgColor: this.data.bgColor,
              hasHead: this.data.hasHead,
              hasTail: this.data.hasTail
            })
            stage.addHistory()
            // stage.addNode({ x, y, text: '新节点' }, true)
            // console.log(node)
            // node.init(stage)
          }
        }
      })[0]
    }
  },
  computed: {
    opt () {
      const option = this.option || {}
      const node = Object.assign({
        borderWidth: 1, // 边框大小
        borderRadius: 3, // 边框圆角大小
        borderColor: '#5F4C0B', // 边框颜色
        padding: 20, // 水平内间距
        height: 30, // 节点高度
        fontHeight: 10, // 文字高度
        point: {}
      }, option.node)
      const point = Object.assign({
        radius: 5, // 半径大小
        bgColor: '#999', // 背景颜色
        borderWidth: 2, // 边框大小
        borderColor: '#666' // 边框颜色
      }, node.point)
      option.node = node
      node.point = point
      return option
    },
    itemStyle () {
      const node = this.opt.node
      return {
        height: `${node.height + node.borderWidth}px`,
        lineHeight: `${node.height - node.borderWidth}px`,
        fontSize: node.fontSize + 'px',
        color: this.data.color,
        backgroundColor: this.data.bgColor,
        border: `${node.borderWidth}px solid ${node.borderColor}`,
        borderRadius: `${node.borderRadius}px`,
        padding: `0 ${node.padding - node.borderWidth / 2}px`
      }
    },
    itemHeadStyle () {
      const node = this.opt.node
      const point = node.point
      return {
        width: point.radius * 2 - point.borderWidth + 'px',
        height: point.radius * 2 - point.borderWidth + 'px',
        top: (node.height - node.borderWidth - (point.radius * 2 + point.borderWidth)) / 2 + 'px',
        left: -(point.radius + point.borderWidth / 2 + node.borderWidth / 2) + 'px',
        border: point.radius * 2 - point.borderWidth > 0 ? `${point.borderWidth}px solid ${point.borderColor}`
          : `${point.borderWidth / 2 + point.radius}px solid ${point.borderColor}`, // 与svg同步，边框向两侧扩展
        borderRadius: point.radius + point.borderWidth + 'px',
        backgroundColor: point.bgColor
      }
    },
    itemTailStyle () {
      const node = this.opt.node
      const point = node.point
      return {
        width: point.radius * 2 - point.borderWidth + 'px',
        height: point.radius * 2 - point.borderWidth + 'px',
        top: (node.height - node.borderWidth - (point.radius * 2 + point.borderWidth)) / 2 + 'px',
        right: -(point.radius + point.borderWidth / 2 + node.borderWidth / 2) + 'px',
        border: point.radius * 2 - point.borderWidth > 0 ? `${point.borderWidth}px solid ${point.borderColor}`
          : `${point.borderWidth / 2 + point.radius}px solid ${point.borderColor}`,
        borderRadius: point.radius + point.borderWidth + 'px',
        backgroundColor: point.bgColor
      }
    },
    itemTextStyle () {
      const node = this.opt.node
      return {
        top: -node.borderWidth + 'px'
      }
    }
  },
  mounted () {
    this.$emit('onload', this)
  }
}
</script>

<style scoped>
  .itembox {
    display: inline-block;
  }
  .item {
    position: relative;
    box-sizing: border-box;
  }
  .item__head, .item__tail {
    position: absolute;
    box-sizing: content-box;
  }
</style>
